package com.psnoted.backend.service;

import com.psnoted.backend.dto.EncryptedStorageData;
import com.psnoted.backend.dto.GetPasswordsResponse;
import com.psnoted.backend.dto.UpdatePasswordsResponse;
import com.psnoted.backend.entity.UserData;
import com.psnoted.backend.repository.UserDataRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

/**
 * 密码数据服务类
 * 实现密码数据的获取和更新业务逻辑
 *
 * @author PSNoted Team
 * @version 1.0.0
 */
@Service
@Transactional
public class PasswordDataService {

    private static final Logger logger = LoggerFactory.getLogger(PasswordDataService.class);

    @Autowired
    private UserDataRepository userDataRepository;

    @Autowired
    private AuthService authService;

    /**
     * 获取用户密码数据
     *
     * @param keyHash 用户密钥哈希
     * @return 密码数据响应
     */
    public GetPasswordsResponse getPasswordData(String keyHash) {
        logger.info("开始获取用户密码数据: keyHash={}", keyHash);

        try {
            // 验证用户是否存在
            if (!authService.userExists(keyHash)) {
                logger.warn("用户不存在: keyHash={}", keyHash);
                return new GetPasswordsResponse(null, null, false);
            }

            // 获取最新的用户数据
            Optional<UserData> latestDataOpt = userDataRepository.findLatestByKeyHash(keyHash);

            if (latestDataOpt.isPresent()) {
                UserData userData = latestDataOpt.get();

                // 构建加密存储数据
                EncryptedStorageData storageData = new EncryptedStorageData(
                    userData.getVersion(),
                    userData.getKeyHash(),
                    userData.getEncryptedData(),
                    userData.getTimestamp()
                );

                // 格式化最后同步时间
                String lastSyncTime = userData.getUpdatedAt()
                    .atZone(ZoneOffset.UTC)
                    .format(DateTimeFormatter.ISO_INSTANT);

                logger.info("成功获取用户密码数据: keyHash={}, timestamp={}", keyHash, userData.getTimestamp());
                return new GetPasswordsResponse(storageData, lastSyncTime, true);
            } else {
                logger.info("用户暂无密码数据: keyHash={}", keyHash);
                return new GetPasswordsResponse(null, null, false);
            }
        } catch (Exception e) {
            logger.error("获取用户密码数据异常: keyHash={}, error={}", keyHash, e.getMessage(), e);
            throw new RuntimeException("获取密码数据失败", e);
        }
    }

    /**
     * 更新用户密码数据
     *
     * @param keyHash 用户密钥哈希
     * @param storageData 加密存储数据
     * @return 更新结果响应
     */
    public UpdatePasswordsResponse updatePasswordData(String keyHash, EncryptedStorageData storageData) {
        logger.info("开始更新用户密码数据: keyHash={}, timestamp={}", keyHash, storageData.getTimestamp());

        try {
            // 验证用户是否存在
            if (!authService.userExists(keyHash)) {
                logger.warn("用户不存在: keyHash={}", keyHash);
                return new UpdatePasswordsResponse(false, null);
            }

            // 检查数据版本冲突
            Optional<UserData> existingDataOpt = userDataRepository.findLatestByKeyHash(keyHash);
            if (existingDataOpt.isPresent()) {
                UserData existingData = existingDataOpt.get();

                // 如果新数据的时间戳小于等于现有数据，说明存在冲突
                if (storageData.getTimestamp() <= existingData.getTimestamp()) {
                    logger.warn("数据版本冲突: keyHash={}, newTimestamp={}, existingTimestamp={}",
                        keyHash, storageData.getTimestamp(), existingData.getTimestamp());

                    // 返回冲突数据
                    EncryptedStorageData conflictData = new EncryptedStorageData(
                        existingData.getVersion(),
                        existingData.getKeyHash(),
                        existingData.getEncryptedData(),
                        existingData.getTimestamp()
                    );

                    return new UpdatePasswordsResponse(false, null, conflictData);
                }
            }

            // 创建或更新用户数据
            UserData userData = existingDataOpt.orElse(new UserData());
            userData.setKeyHash(keyHash);
            userData.setVersion(storageData.getVersion());
            userData.setEncryptedData(storageData.getEncryptedData());
            userData.setTimestamp(storageData.getTimestamp());
            userData.setCreatedAt(userData.getCreatedAt() != null ? userData.getCreatedAt() : LocalDateTime.now());
            userData.setUpdatedAt(LocalDateTime.now());

            UserData savedData = userDataRepository.save(userData);

            // 格式化服务器同步时间
            String serverSyncTime = savedData.getUpdatedAt()
                .atZone(ZoneOffset.UTC)
                .format(DateTimeFormatter.ISO_INSTANT);

            logger.info("成功更新用户密码数据: keyHash={}, timestamp={}", keyHash, storageData.getTimestamp());
            return new UpdatePasswordsResponse(true, serverSyncTime);

        } catch (Exception e) {
            logger.error("更新用户密码数据异常: keyHash={}, error={}", keyHash, e.getMessage(), e);
            throw new RuntimeException("更新密码数据失败", e);
        }
    }

    /**
     * 删除用户密码数据
     *
     * @param keyHash 用户密钥哈希
     * @return 删除是否成功
     */
    public boolean deletePasswordData(String keyHash) {
        logger.info("开始删除用户密码数据: keyHash={}", keyHash);

        try {
            userDataRepository.deleteByKeyHash(keyHash);
            logger.info("成功删除用户密码数据: keyHash={}", keyHash);
            return true;
        } catch (Exception e) {
            logger.error("删除用户密码数据异常: keyHash={}, error={}", keyHash, e.getMessage(), e);
            throw new RuntimeException("删除密码数据失败", e);
        }
    }

    /**
     * 检查用户是否有密码数据
     *
     * @param keyHash 用户密钥哈希
     * @return 是否有数据
     */
    public boolean hasPasswordData(String keyHash) {
        return userDataRepository.existsByKeyHash(keyHash);
    }

    /**
     * 获取用户数据统计信息
     *
     * @param keyHash 用户密钥哈希
     * @return 数据数量
     */
    public long getPasswordDataCount(String keyHash) {
        return userDataRepository.countByKeyHash(keyHash);
    }
}